/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package onpu_dms_xls.kernel.common;

import onpu_dms_xls.kernel.common.pdf.PDF_TextLabelData;
import onpu_dms_xls.kernel.common.XML_Parsers.SAX_XML_Template_Parser;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


import onpu_dms_xls.exceptions.MyException;
import onpu_dms_xls.exceptions.MyXMLException;
import onpu_dms_xls.kernel.common.XML_Parsers.PDF_Layout_XML_Parser;
import onpu_dms_xls.kernel.common.logAndDebug.Debug;
import onpu_dms_xls.kernel.common.logAndDebug.LoggingFacade;
import onpu_dms_xls.kernel.common.pdf.PDF_Extract_LayoutTemplate;
import onpu_dms_xls.kernel.common.pdf.composite.ExtractComponent;
import onpu_dms_xls.kernel.common.pdf.composite.ExtractCompositeComponent;
import onpu_dms_xls.kernel.common.pdf.composite.ExtractLabel;
import onpu_dms_xls.kernel.common.pdf.composite.ExtractMarkLabels;
import onpu_dms_xls.kernel.common.pdf.composite.new_PDF_Layout_XML_Parser;
import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.util.CellRangeAddress;

/**
 *
 * @author snbm
 */
public class Util {
    

    private static final HashMap<Integer, Double> fontsAndTheirSizesIn_ppt = new HashMap<Integer, Double>();
    private static final HashMap<Integer, Double> CAPS_fontsAndTheirSizesIn_ppt = new HashMap<Integer, Double>();
    static {
        fontsAndTheirSizesIn_ppt.put(7, 4.1);
        fontsAndTheirSizesIn_ppt.put(8, 4.75);
        fontsAndTheirSizesIn_ppt.put(9, 5.4);
        CAPS_fontsAndTheirSizesIn_ppt.put(9, 5.4);
        CAPS_fontsAndTheirSizesIn_ppt.put(8, 4.85);
        CAPS_fontsAndTheirSizesIn_ppt.put(7, 4.2);
        CAPS_fontsAndTheirSizesIn_ppt.put(6, 3.6);
        CAPS_fontsAndTheirSizesIn_ppt.put(5, 3.0);
    }

    public static VariableDeclaration[] generateVariablesDeclarationsArrayFromXMLFile(File xmlFile)
            throws FileNotFoundException {
        VariableDeclaration[] vdArr = null;

        SAX_XML_Template_Parser spe = new SAX_XML_Template_Parser();
        vdArr = spe.runExample(xmlFile.getAbsolutePath());

        return vdArr;
    }

    public static PDF_Extract_LayoutTemplate getPDFVipiskaTemplateFromPDFXMLTemplate(File xmlFile)
            throws FileNotFoundException {
        PDF_Extract_LayoutTemplate res = null;

        res = PDF_Layout_XML_Parser.getInstance().run(xmlFile.getAbsolutePath());

        return res;
    }

    public static ExtractComponent getNewPDFExtractTemplateFromPDFXMLTemplate(File xmlFile)
            throws FileNotFoundException {
        ExtractComponent res = null;

        res = new_PDF_Layout_XML_Parser.getInstance().run(xmlFile.getAbsolutePath());

        return res;
    }

    public static double get_ONE_CHAR_SIZE(ExtractLabel label) {
        double res;
        if (label instanceof ExtractMarkLabels) {
            if (label.getFontSize() >= 5
                    && label.getFontSize() <= 9) {
                res = CAPS_fontsAndTheirSizesIn_ppt.get(new Integer(label.getFontSize()));
            } else {
                res = CAPS_fontsAndTheirSizesIn_ppt.get(7);
            }
            return res;
        }

        if (label.getFontSize() == 8 || label.getFontSize() == 9 || label.getFontSize() == 7) {
            res = fontsAndTheirSizesIn_ppt.get(new Integer(label.getFontSize()));
        } else {
            res = fontsAndTheirSizesIn_ppt.get(8);
        }
        return res;
    }

        /**
    separate by ' ' and '-'
     */
    public static ArrayList<String> getWordsFromString(String data) {
        ArrayList<String> res = new ArrayList<String>();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < data.toCharArray().length; i++) {
            char currentChar = data.charAt(i);
            if (currentChar != ' '
                    && currentChar != '-'
                    && currentChar != ':') {
                sb.append(currentChar);
                if (i == data.toCharArray().length - 1) {
                    res.add(sb.toString());
                }
            } else {
                sb.append(currentChar);
                res.add(sb.toString());
                sb = new StringBuilder();
            }
        }
        return res;
    }

    public static VariableDataTypes stringToDataType(String typeName) {

        if (typeName.equals(VariableDataTypes.STRING.getValue())) {
            return VariableDataTypes.STRING;
        } else if (typeName.equals(VariableDataTypes.INT.getValue())) {
            return VariableDataTypes.INT;
        } else if (typeName.equals(VariableDataTypes.DOUBLE.getValue())) {
            return VariableDataTypes.DOUBLE;
        } else if (typeName.equals(VariableDataTypes.DATE.getValue())) {
            return VariableDataTypes.DATE;
        } else {
            return null;
        }
    }

    public static String getCellData(Cell cell) {
        try {
            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_BLANK:
                    return null;
                case Cell.CELL_TYPE_STRING:
                    return cell.getRichStringCellValue().getString();
                case Cell.CELL_TYPE_NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        return cell.getDateCellValue().toString();
                    } else {
                        return "" + (int) cell.getNumericCellValue();
                    }
                default:
                    return "" + cell;
            }
        } catch (NullPointerException e) {
            return "";
        }
    }

    public static String fillQueryWithVariablesValues(
            String startQuery,
            VariableDeclaration[] varDeclArray) throws MyXMLException {

        LoggingFacade.trace.debug("fillQueryWithVariablesValues, working with query:" + startQuery);
        Pattern p = Pattern.compile("\\u0024[a-zA-Z\\d\\u002E\\u005F]*");
        Matcher m = p.matcher(startQuery);
        while (m.find()) {
            String variableNameInQuery = m.group();
            String variableName = variableNameInQuery.substring(1);
            LoggingFacade.trace.debug("|found match, start:" + m.start() + " end:" + m.end() + " for variable:" + variableName);
            //get the variable value
            String varValue = null;
            for (VariableDeclaration vd : varDeclArray) {
                if (vd.getVarName().equals(variableName)) {
                    varValue = vd.getValue();

                }
            }
            if (varValue == null) {
                throw new MyXMLException("Util", "fillQueryWithVariablesValues", "finding a variable data", "no variable" + variableName + " data found");
            }
            LoggingFacade.trace.debug("|found variable value in VarDeclArray, name: " + variableName + " value: " + varValue);

            LoggingFacade.trace.debug("|replacing : " + variableNameInQuery + " in " + startQuery + " with " + varValue);
            startQuery = startQuery.replace(variableNameInQuery, varValue);
        }
        return startQuery;
    }

    public static String filltemplateNamewithVariablesValues(
            String nameTemplate,
            VariableDeclaration[] varDeclArray) throws MyXMLException {
        LoggingFacade.trace.debug("filltemplateNamewithVariablesValues, working with name template:" + nameTemplate);
        Pattern p = Pattern.compile("\\u0024[a-zA-Z\\d\\u002E\\u005F]*");
        Matcher m = p.matcher(nameTemplate);
        while (m.find()) {
            String token = m.group();
            //костиль. невелечкий. :-)
            if (token.endsWith("_")) {
                token = token.substring(0, token.length() - 1);
            }
            String variableNameInNameTemplate = token;
            String variableName = variableNameInNameTemplate.substring(1);
            LoggingFacade.trace.debug("|found match, start:" + m.start() + " end:" + m.end() + " for variable:" + variableName);
            //get the variable value
            String varValue = null;
            for (VariableDeclaration vd : varDeclArray) {
                if (vd.getVarName().equals(variableName)) {
                    varValue = vd.getValue();

                }
            }
            if (varValue == null) {
                throw new MyXMLException("Common", "filltemplateNamewithVariablesValues", "finding a variable data", "no variable" + variableName + " data found");
            }
            LoggingFacade.trace.debug("|found variable value in VarDeclArray, name: " + variableName + " value: " + varValue);

            LoggingFacade.trace.debug("|replacing : " + variableNameInNameTemplate + " in " + nameTemplate + " with " + varValue);
            nameTemplate = nameTemplate.replace(variableNameInNameTemplate, varValue);
        }
        return nameTemplate;
    }

    public static String getTempFolderFromInputXML(String xml) throws MyException {
        LoggingFacade.trace.debug("call");
        String result = null;
        Scanner sc = new Scanner(xml);
        sc.useDelimiter("temporaryFolder>");
        if (sc.hasNext()) {
            String token = sc.next();
            LoggingFacade.trace.debug("first token: " + token);
            token = sc.next();
            LoggingFacade.trace.debug("second token:" + token);
            result = token.substring(0, token.length() - 2);
            LoggingFacade.trace.debug("result (temp folder path):" + result);
        }

        if (result == null && result.contains(" ")) {
            throw new MyException("Util", "getTempFolderFromInputXML", "Not correct temporary folder name, try something without spaces");
        }
        return result;

//
//        Scanner sc = new Scanner (xml);
//        sc.useDelimiter("temporaryFolder");
//        while (sc.hasNext()){
//            String token = sc.next();
//            LoggingFacade.trace.info("found token:"+token);
//            if (token.matches(">([a-zA-Z]:)?(\\\\[a-zA-Z0-9_]+)+</")){
//                LoggingFacade.trace.info("MATCH: "+token);
//                result = token.substring(1, token.length()-2);
//                LoggingFacade.trace.info("RESULT of getTempFolderFromInputXML: "+result);
//            }
//        }
    }

    @Deprecated
    public static Integer getDebugMode(String inputXML){
        LoggingFacade.trace.debug("call");
        if (!inputXML.contains("debugMode>")) {
            LoggingFacade.trace.info("exiting from getDebugMode, no such element found in inputXML");
            return null;
        }
        String result = null;
        Scanner sc = new Scanner(inputXML);
        sc.useDelimiter("debugMode>");
        if (sc.hasNext()) {
            String token = sc.next();
            LoggingFacade.trace.debug("first token: " + token);
            token = sc.next();
            LoggingFacade.trace.debug("second token:" + token);
            result = token.substring(0, token.length() - 2);
            LoggingFacade.trace.debug("result (debug mode):" + result);
        }

        if (result == null && result.contains(" ")) {
            return null;
        }
        return new Integer(Debug.getDebugModeFromName(result));
    }


    public static void copyRow(HSSFWorkbook workbook, HSSFSheet worksheet, int sourceRowNum, int destinationRowNum) {
        LoggingFacade.trace.debug("call, sourceRowNum="+sourceRowNum+", destinationRowNum="+destinationRowNum);
        // Get the source / new row
        HSSFRow newRow = worksheet.getRow(destinationRowNum);
        HSSFRow sourceRow = worksheet.getRow(sourceRowNum);
        int sourceRowHeigh = sourceRow.getHeight();

        // If the row exist in destination, push down all rows by 1 else create a new row
        if (newRow != null) {
            worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
        } else {
            newRow = worksheet.createRow(destinationRowNum);
        }

        newRow.setHeight((short) sourceRowHeigh);

        // Loop through source columns to add to new row
        for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
            // Grab a copy of the old/new cell
            HSSFCell oldCell = sourceRow.getCell(i);
            HSSFCell newCell = newRow.createCell(i);

            // If the old cell is null jump to next cell
            if (oldCell == null) {
                newCell = null;
                continue;
            }

            // Copy style from old cell and apply to new cell
            HSSFCellStyle newCellStyle = workbook.createCellStyle();
            newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
            newCell.setCellStyle(newCellStyle);

            // If there is a cell comment, copy
            if (newCell.getCellComment() != null) {
                newCell.setCellComment(oldCell.getCellComment());
            }

            // If there is a cell hyperlink, copy
            if (oldCell.getHyperlink() != null) {
                newCell.setHyperlink(oldCell.getHyperlink());
            }

            // Set the cell data type
            newCell.setCellType(oldCell.getCellType());

            // Set the cell data value
            switch (oldCell.getCellType()) {
                case Cell.CELL_TYPE_BLANK:
                    newCell.setCellValue(oldCell.getStringCellValue());
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    newCell.setCellValue(oldCell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_ERROR:
                    newCell.setCellErrorValue(oldCell.getErrorCellValue());
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    newCell.setCellFormula(oldCell.getCellFormula());
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    newCell.setCellValue(oldCell.getNumericCellValue());
                    break;
                case Cell.CELL_TYPE_STRING:
                    newCell.setCellValue(oldCell.getRichStringCellValue());
                    break;
            }
        }

        // If there are are any merged regions in the source row, copy to new row
        for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
            CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
            if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
                CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
                        (newRow.getRowNum()
                        + (cellRangeAddress.getFirstRow()
                        - cellRangeAddress.getLastRow())),
                        cellRangeAddress.getFirstColumn(),
                        cellRangeAddress.getLastColumn());
                worksheet.addMergedRegion(newCellRangeAddress);
            }
        }
    }
}
